package com.errol.batchprocessor.payroll.advisorimpl.common;

import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.renjia.constant.Constant;
import com.renjia.dao.BusPayrollRecordDetailMapper;
import com.renjia.dao.BusPayrollRecordMapper;
import com.renjia.entity.BusPayrollRecord;
import com.renjia.entity.BusPayrollRecordDetail;
import com.renjia.entity.CoreCustomerPayrollRate;
import com.renjia.enums.CheckAcceptStatusEnum;
import com.renjia.enums.PayrollDetailValidateStatusEnum;
import com.renjia.enums.ServiceChargeTypeEnum;
import com.renjia.enums.SwitchEnum;
import com.renjia.properties.SpecialCustomerProperties;
import com.renjia.service.CoreCustomerPayrollRateService;
import com.renjia.service.generic.log.LogService;
import com.renjia.service.generic.support.payroll.PayrollAmountSupportService;
import com.renjia.service.module.employeeaddition.advisorimpl.payroll.payload.PayrollEmployeeBatchPayload;
import com.renjia.service.module.employeeaddition.advisorimpl.payroll.payload.PayrollEmployeePiecePayload;
import com.renjia.service.module.employeeaddition.advisorimpl.payroll.payload.PayrollEmployeeSinglePayload;
import com.renjia.service.module.payroll.advisor.upload.PayrollUploadCheckAdvisor;
import com.renjia.service.module.payroll.advisor.upload.PayrollUploadCreateAdvisor;
import com.renjia.service.module.payroll.advisor.verify.*;
import com.renjia.service.module.payroll.advisorimpl.common.multiemployeeinbatch.PayLimitImportAdvisorImpl;
import com.renjia.service.module.payroll.advisorimpl.payload.PayLimitPayload;
import com.renjia.service.module.payroll.advisorimpl.payload.PayrollUploadBatchPayload;
import com.renjia.service.module.payroll.advisorimpl.payload.PayrollUploadSinglePayload;
import com.renjia.util.caculatepayroll.CalculatePayrollResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * 发放金额相关扩展
 *
 * @author zhang xiao bin
 * @version v1.0
 * @date 2021/03/07
 * @since v5.0.6
 **/
@Service
public class PayAmountAdvisorImpl
        extends PayLimitImportAdvisorImpl
        implements PayrollUploadCheckAdvisor, PayrollUploadCreateAdvisor, PayrollVerifyBatchStartAdvisor, PayrollVerifySingleValidateAdvisor,
        PayrollVerifySingleProcessAdvisor, PayrollVerifySinglePostAdvisor, PayrollVerifyPiecePostAdvisor {

    private final BusPayrollRecordDetailMapper busPayrollRecordDetailMapper;
    private final PayrollAmountSupportService payrollAmountSupportService;
    private final BusPayrollRecordMapper busPayrollRecordMapper;
    private final LogService logService;
    @Autowired
    private CoreCustomerPayrollRateService coreCustomerPayrollRateService;

    public PayAmountAdvisorImpl(BusPayrollRecordDetailMapper busPayrollRecordDetailMapper, PayrollAmountSupportService payrollAmountSupportService,
                                SpecialCustomerProperties specialCustomerProperties,
                                BusPayrollRecordMapper busPayrollRecordMapper, LogService logService) {
        super(payrollAmountSupportService, specialCustomerProperties, logService);
        this.busPayrollRecordDetailMapper = busPayrollRecordDetailMapper;
        this.payrollAmountSupportService = payrollAmountSupportService;
        this.busPayrollRecordMapper = busPayrollRecordMapper;
        this.logService = logService;
    }

    @Override
    public boolean shallProcess(@NonNull PayrollEmployeeBatchPayload advisorPayload) {
        return true;
    }

    @Override
    public int priority() {
        return 111;
    }

    @Override
    public boolean doCheckBeforePayrollSavedAtUploadStage(@NonNull PayrollUploadBatchPayload batchPayload) {
        // 保存费用单之前检查客户配置
        if (batchPayload.getCoreCustomerChannelMerchant().getMonthLimitAmount() == null) {
            batchPayload.getErrMsgList().add("该客户未设置当月最大额度");
            return false;
        }
        if (batchPayload.getCoreCustomerChannelMerchant().getLimitAmount() == null) {
            batchPayload.getErrMsgList().add("该客户未设置最大额度");
            return false;
        }
        if (SwitchEnum.ON.getCode2().equals(batchPayload.getCoreCustomerChannelMerchant().getServiceChargeType())) {
            //查询是否有发放中的数据
            Wrapper<BusPayrollRecord> wrapper = Condition.wrapper();
            wrapper.eq("customer_id", batchPayload.getCoreCustomerChannelMerchant().getCustomerId());
            wrapper.eq("channel_merchant_id", batchPayload.getCoreCustomerChannelMerchant().getChannelMerchantId());
            wrapper.ne("check_accept_status", CheckAcceptStatusEnum.CANCEL.getCode());
            wrapper.in("payroll_status", "0,1,5,7");
            int count = busPayrollRecordMapper.selectCount(wrapper);
            if (count > Constant.COMMON_ZERO) {
                batchPayload.getErrMsgList().add("当前客户设置了服务费阶梯扣减，请优先处理已有未完成批次，处理完后再导入新批次；");
                return false;
            }
            //查询客户的阶梯计费配置
            Wrapper<CoreCustomerPayrollRate> coreCustomerPayrollRateWrapper = Condition.wrapper();
            coreCustomerPayrollRateWrapper.eq("channel_merchant_id", batchPayload.getCoreCustomerChannelMerchant().getChannelMerchantId());
            coreCustomerPayrollRateWrapper.eq("customer_id", batchPayload.getCoreCustomerChannelMerchant().getCustomerId());
            List<CoreCustomerPayrollRate> coreCustomerPayrollRateList = coreCustomerPayrollRateService.selectList(coreCustomerPayrollRateWrapper);
            if (coreCustomerPayrollRateList == null) {
                batchPayload.getErrMsgList().add("请先配置阶梯费率");
                return false;
            }
            batchPayload.setCoreCustomerPayrollRateList(coreCustomerPayrollRateList);

        }
        // 客户-服务商 服务费相关配置想未检查 null
        return true;
    }

    @Override
    public boolean doAfterNewPayrollRecordAtUploadStage(@NonNull PayrollUploadBatchPayload batchPayload) {
        // 创建批次时，客户服务费率
        batchPayload.getBatchEntity().setManageRate(batchPayload.getCoreCustomerChannelMerchant().getManageRate());
        batchPayload.getBatchEntity().setManageCostType(batchPayload.getCoreCustomerChannelMerchant().getManageCostType());
        batchPayload.getBatchEntity().setPersonalManageRate(batchPayload.getCoreCustomerChannelMerchant().getPersonalManageRate());
        //5.2.0
        batchPayload.getBatchEntity().setServiceChargeType(batchPayload.getCoreCustomerChannelMerchant().getServiceChargeType());
        batchPayload.getBatchEntity().setSumType(batchPayload.getCoreCustomerChannelMerchant().getSumType());
        // 验收单总人数
        batchPayload.getBatchEntity().setTotalNumber(batchPayload.getPayrollDetailExcelPoList().size());
        batchPayload.getBatchEntity().setPersonNumber(Constant.COMMON_ZERO);
        // 个人应发
        batchPayload.getBatchEntity().setPersonalShouldSalary(BigDecimal.ZERO);
        // 应发（原）总额（结算）、佣金（服务费）、工资（实发）
        batchPayload.getBatchEntity().setShouldPayAmount(BigDecimal.ZERO);
        batchPayload.getBatchEntity().setShouldPayBrokerage(BigDecimal.ZERO);
        batchPayload.getBatchEntity().setShouldPaySalary(BigDecimal.ZERO);
        // 实发总额、佣金、工资
        batchPayload.getBatchEntity().setInfactPayAmount(BigDecimal.ZERO);
        batchPayload.getBatchEntity().setInfactPayBrokerage(BigDecimal.ZERO);
        batchPayload.getBatchEntity().setInfactPaySalary(BigDecimal.ZERO);
        return true;
    }

    @Override
    public boolean doAfterNewPayrollDetailAtUploadStage(@NonNull PayrollUploadSinglePayload singlePayload, @NonNull PayrollUploadBatchPayload batchPayload) {
        // 创建明细时，初始化各项金额
        BusPayrollRecordDetail detail = singlePayload.getBusPayrollRecordDetail();
        detail.setReturnAmount(BigDecimal.ZERO);
        if (StringUtils.isNotEmpty(singlePayload.getPayrollDetailPo().getPersonalShouldSalary())) {
            try {
                BigDecimal personalShouldSalary = new BigDecimal(singlePayload.getPayrollDetailPo().getPersonalShouldSalary());
                BusPayrollRecord payroll = batchPayload.getBatchEntity();
                CalculatePayrollResult calculatePayrollResult = new CalculatePayrollResult();
                if (ServiceChargeTypeEnum.STEP.getCode().equals(payroll.getServiceChargeType())) {
                    calculatePayrollResult = coreCustomerPayrollRateService.getPayrollRate(detail, payroll, personalShouldSalary, batchPayload.getCoreCustomerPayrollRateList());
                } else {
                    calculatePayrollResult = payrollAmountSupportService.getCalculatePayrollResult(personalShouldSalary, payroll);
                    detail.setManageRate(payroll.getManageRate());
                    detail.setPersonalManageRate(payroll.getPersonalManageRate());
                }
                detail.setPersonalShouldSalary(personalShouldSalary);
                // 个人应发
                // 工资条应发金额，仅展示工资条使用
                detail.setSlipShouldPaySalary(calculatePayrollResult.getInfactPaySalary());
                // 结算、服务费、实发
                detail.setShouldPayAmount(calculatePayrollResult.getInfactPayAmount());
                detail.setShouldPayBrokerage(calculatePayrollResult.getInfactPayBrokerage());
                detail.setInfactPayAmount(calculatePayrollResult.getInfactPaySalary());
                // 客户自留服务费
                detail.setCustManagerFree(calculatePayrollResult.getCustManagerFree());
                // 累计到 busPayrollRecord
                payrollAmountSupportService.addDetailToPayrollRecord(batchPayload.getBatchEntity(), calculatePayrollResult);
                batchPayload.getBatchEntity().setPersonNumber(batchPayload.getBatchEntity().getPersonNumber() + 1);
            } catch (Exception e) {
                // 应发金额解析失败
            }
        }
        return true;
    }

    @Override
    public boolean doBeforeModifyPayrollDetailAtUploadStage(@NonNull PayrollUploadSinglePayload singlePayload, @NonNull PayrollUploadBatchPayload batchPayload) {
        // 编辑明细时，如果明细验证通过，则需要先从 payrollRecord 扣减已累计的当前明细的金额
        if (!singlePayload.isModifyMode()) {
            // 新增
        } else {
            BusPayrollRecordDetail detail = singlePayload.getBusPayrollRecordDetail();
            // 编辑验证通过的记录时，需要回滚累计金额
            if (PayrollDetailValidateStatusEnum.VALIDATE_PASS.getCode().equals(detail.getValidStatus())) {
                //5.2.0 添加阶梯计价
                CalculatePayrollResult calculatePayrollResult = new CalculatePayrollResult();
                if (ServiceChargeTypeEnum.STEP.getCode().equals(batchPayload.getBatchEntity().getServiceChargeType())) {
                    calculatePayrollResult = coreCustomerPayrollRateService.getPayrollRate(singlePayload.getBusPayrollRecordDetail(), batchPayload.getBatchEntity(),
                            singlePayload.getBusPayrollRecordDetail().getPersonalShouldSalary(), batchPayload.getCoreCustomerPayrollRateList());
                } else {
                    calculatePayrollResult = payrollAmountSupportService.getCalculatePayrollResult(singlePayload.getBusPayrollRecordDetail().getPersonalShouldSalary(),
                            batchPayload.getBatchEntity());
                    detail.setManageRate(batchPayload.getBatchEntity().getManageRate());
                    detail.setPersonalManageRate(batchPayload.getBatchEntity().getPersonalManageRate());
                }
                payrollAmountSupportService.subtractDetailFromPayrollRecord(batchPayload.getBatchEntity(), calculatePayrollResult);
                batchPayload.getBatchEntity().setPersonNumber(batchPayload.getBatchEntity().getPersonNumber() - 1);
            }
        }
        return true;
    }

    @Override
    public boolean doPrepareOnBatchStartAtVerifyStage(@NonNull PayrollEmployeeBatchPayload batchPayload) {
        if (batchPayload.getPayLimitPayload() == null) {
            batchPayload.setPayLimitPayload(new PayLimitPayload(batchPayload.getCoreCustomerChannelMerchant()));
        }
        return true;
    }

    @Override
    public boolean doValidateBeforeFindEmployeeAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload,
                                                             @NonNull PayrollEmployeeBatchPayload batchPayload) {
        // 验证之前检查个人应发和实发金额
        if (singlePayload.getSingleEntity().getPersonalShouldSalary() == null) {
            singlePayload.getErrMsgList().add("应发金额为空或不是数字");
            return false;
        }
        if (singlePayload.getSingleEntity().getPersonalShouldSalary().compareTo(BigDecimal.ZERO) <= 0) {
            singlePayload.getErrMsgList().add("应发金额必须大于 0 元");
            return false;
        }
        if (singlePayload.getSingleEntity().getInfactPayAmount().compareTo(BigDecimal.ZERO) <= 0) {
            singlePayload.getErrMsgList().add("实发金额必须大于 0 元");
        }
        return true;
    }

    @Override
    public boolean doExecuteOnEmployeeInfoSavedAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload,
                                                             @NonNull PayrollEmployeeBatchPayload batchPayload) {
        //5.2.0添加服务费小于0的过滤
        if (singlePayload.getSingleEntity().getShouldPayBrokerage().compareTo(BigDecimal.ZERO) < Constant.COMMON_ZERO) {
            singlePayload.getErrMsgList().add("服务费不能小于0");
            return false;
        }
        BigDecimal inFactPayAmount = getInFactPayAmount(singlePayload, piecePayload, batchPayload);
        // 获取当月已使用额度，累加当次额度，如果超过月限额，则验证失败；payResultTime 线上发放为 null、线下发放为实际发放时间
        //5.3.0如果是人员重复的，使用使用累加的形式，如果校验人员重复使用原有的逻辑
        if (SwitchEnum.ON.getCode2().equals(batchPayload.getCoreCustomerChannelMerchant().getAllowEmployeeRepeat())) {
            BigDecimal monthlyUsedAmount = payrollAmountSupportService.getMonthlyUsedAmountOfEmployee(singlePayload.getCoreEmployee().getId(),
                    singlePayload.getSingleEntity().getPayTime());
            if (monthlyUsedAmount.add(inFactPayAmount).compareTo(batchPayload.getPayLimitPayload().getMonthLimitAmount()) > 0) {
                singlePayload.getErrMsgList().add(String.format("当月最高限额：￥%s, 当月已发放：￥%s（不含当次）", batchPayload.getPayLimitPayload().getMonthLimitAmount(), monthlyUsedAmount));
                return false;
            } else {
                logService.debug("【人员导入批处理】【" + batchPayload.getBatchEntity().getBatchNo() + "】【" + singlePayload.getSingleEntity().getId() + "】月限额验证通过");
            }
            return true;
        }
        return true;

    }

    @Override
    public boolean doCleanUpOnPayrollDetailProcessPostAtVerifyStage(@NonNull PayrollEmployeeSinglePayload singlePayload, @NonNull PayrollEmployeePiecePayload piecePayload,
                                                                    @NonNull PayrollEmployeeBatchPayload batchPayload) {
        // 明细验证结束（保存验证结果）后触发，如果验证失败，将费用计算结果累加分片，在分片结束后从发放记录扣减
        // 在编辑模式下，验证失败的不需要保存，所以这个方法也不需要调用
        if (PayrollDetailValidateStatusEnum.VALIDATE_FAIL.getCode().equals(singlePayload.getSingleEntity().getValidStatus())) {
            CalculatePayrollResult calculatePayrollResult = new CalculatePayrollResult();
            if (ServiceChargeTypeEnum.STEP.getCode().equals(batchPayload.getBatchEntity().getServiceChargeType())) {
                calculatePayrollResult = coreCustomerPayrollRateService.getPayrollRate(singlePayload.getSingleEntity(), batchPayload.getBatchEntity(),
                        singlePayload.getSingleEntity().getPersonalShouldSalary(), batchPayload.getCoreCustomerPayrollRateList());
            } else {
                calculatePayrollResult = payrollAmountSupportService.getCalculatePayrollResult(singlePayload.getSingleEntity().getPersonalShouldSalary(),
                        batchPayload.getBatchEntity());
                singlePayload.getSingleEntity().setPersonalManageRate(batchPayload.getBatchEntity().getPersonalManageRate());
                singlePayload.getSingleEntity().setManageRate(batchPayload.getBatchEntity().getManageRate());
            }
            payrollAmountSupportService.accumulateCalculatePayrollResult(piecePayload.getFailedCalculatePayrollResult(), calculatePayrollResult);
            piecePayload.setPersonNumber(piecePayload.getPersonNumber() + 1);
        }
        return true;
    }

    @Override
    public boolean doCleanUpOnPayrollDetailPieceProcessPostAtVerifyStage(@NonNull PayrollEmployeePiecePayload piecePayload, @NonNull PayrollEmployeeBatchPayload batchPayload) {
        // 分片结束，如果有验证失败人员，对 busPayrollRecord 加锁，然后从发放记录扣减分片中累计的金额
        if (piecePayload.getPersonNumber() > 0) {
            synchronized (batchPayload.getBatchEntity()) {
                payrollAmountSupportService.subtractDetailFromPayrollRecord(batchPayload.getBatchEntity(), piecePayload.getFailedCalculatePayrollResult());
                batchPayload.getBatchEntity().setPersonNumber(batchPayload.getBatchEntity().getPersonNumber() - piecePayload.getPersonNumber());
            }
        }
        return true;
    }
}
